// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.linqingying.gitcode.pullrequest.data.provider

import com.intellij.openapi.Disposable
import com.intellij.openapi.progress.EmptyProgressIndicator
import com.linqingying.gitcode.api.data.pullrequest.GCPullRequestFileViewedState
import com.linqingying.gitcode.pullrequest.data.GCPRIdentifier
import com.linqingying.gitcode.pullrequest.data.service.GCPRFilesService
import com.linqingying.gitcode.util.LazyCancellableBackgroundProcessValue
import java.util.concurrent.CompletableFuture

internal class GCPRViewedStateDataProviderImpl(
  private val filesService: GCPRFilesService,
  private val pullRequestId: GCPRIdentifier,
) : GCPRViewedStateDataProvider,
    Disposable {

  private val viewedState = LazyCancellableBackgroundProcessValue.create { indicator ->
    filesService
      .loadFiles(indicator, pullRequestId)
      .thenApply { files -> files.associateBy({ it.path }, { it.viewerViewedState }) }
  }

  override fun loadViewedState(): CompletableFuture<Map<String, GCPullRequestFileViewedState>> = viewedState.value

  override fun getViewedState(): Map<String, GCPullRequestFileViewedState>? {
    if (!viewedState.isCached) return null

    return runCatching { viewedState.value.getNow(emptyMap()) }.getOrDefault(emptyMap())
  }

  override fun updateViewedState(path: String, isViewed: Boolean) {
    val result = filesService.updateViewedState(EmptyProgressIndicator(), pullRequestId, path, isViewed)

    viewedState.combineResult(result) { files, _ ->
      val newState = if (isViewed) GCPullRequestFileViewedState.VIEWED else GCPullRequestFileViewedState.UNVIEWED

      files + (path to newState)
    }
  }

  override fun addViewedStateListener(parent: Disposable, listener: () -> Unit) =
    viewedState.addDropEventListener(parent, listener)

  override fun reset() = viewedState.drop()

  override fun dispose() = reset()
}
